package com.easylinkin.linkappapi.crane.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.crane.dto.CraneBusinessDayStatsics;
import com.easylinkin.linkappapi.crane.dto.CraneBusinessDayStatsicsReq;
import com.easylinkin.linkappapi.crane.entity.CraneBusinessRecord;
import com.easylinkin.linkappapi.crane.mapper.CraneBusinessRecordMapper;
import com.easylinkin.linkappapi.crane.service.ICraneBusinessRecordService;
import com.easylinkin.linkappapi.deviceattribute.entity.DeviceAttribute;
import com.easylinkin.linkappapi.deviceattribute.service.DeviceAttributeService;
import com.easylinkin.linkappapi.deviceattributestatus.entity.DeviceAttributeStatus;
import com.easylinkin.linkappapi.deviceattributestatus.service.DeviceAttributeStatusService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 吊机业务数据记录表 服务实现类
 *
 * @author xy
 * @since 2025-06-23
 */
@Service
public class CraneBusinessRecordServiceImpl extends ServiceImpl<CraneBusinessRecordMapper, CraneBusinessRecord> implements ICraneBusinessRecordService {

    @Autowired
    private LinkappUserContextProducer linkappUserContextProducer;

    @Autowired
    private DeviceAttributeService deviceAttributeService;

    @Override
    public IPage<CraneBusinessRecord> findPage(RequestModel<CraneBusinessRecord> requestModel) {
        IPage<CraneBusinessRecord> page = baseMapper.findPage(requestModel.getPage(), requestModel.getCustomQueryParams());

        Integer interval = null;
        // 检查是否需要拼接单位
        List<CraneBusinessRecord> records = page.getRecords();
        if (requestModel.getCustomQueryParams() != null &&
            Boolean.TRUE.equals(requestModel.getCustomQueryParams().getAppendUnit())) {
            appendUnitsToRecords(records);
        }
        if (requestModel.getCustomQueryParams() != null &&
            requestModel.getCustomQueryParams().getInterval() != null) {
            interval = requestModel.getCustomQueryParams().getInterval();
        }

        if (CollectionUtil.isNotEmpty(records) && interval != null && interval > 0
                && records.size() > interval && requestModel.getPage().getSize() == -1) {
            // 按间隔数取值
            List<CraneBusinessRecord> result = new ArrayList<>();
            for (int i = 0; i < records.size(); i += interval) {
                result.add(records.get(i));
            }
            page.setRecords(result);
        }
        
        return page;
    }

    /**
     * 为记录添加单位
     * @param records 记录列表
     */
    private void appendUnitsToRecords(List<CraneBusinessRecord> records) {
        if (CollectionUtil.isEmpty(records)) {
            return;
        }

        // 获取第一个记录的设备编码，用于获取物模型定义
        String deviceCode = records.get(0).getDeviceCode();
        if (deviceCode == null) {
            return;
        }

        // 获取设备物模型定义
        List<DeviceAttribute> props = deviceAttributeService.getDeviceAttributesByDeviceCode(deviceCode);

        if (CollectionUtil.isEmpty(props)) {
            return;
        }

        // 构建属性编码到单位的映射
        Map<String, String> propCodeToUnitMap = new HashMap<>();
        for (DeviceAttribute prop : props) {
            try {
                if (prop.getIdentifier() != null && StringUtils.isNotBlank(prop.getSpecs())) {
//                {"unit":"m"}
                    JSONObject jsonObject = JSON.parseObject(prop.getSpecs());
                    propCodeToUnitMap.put(prop.getIdentifier(), jsonObject.getString("unit"));
                }
            }catch (Exception e){
            }
        }

        // 为每条记录添加单位
        for (CraneBusinessRecord record : records) {
            appendUnitToRecord(record, propCodeToUnitMap);
        }
    }

    /**
     * 为单条记录添加单位
     * @param record 记录
     * @param propCodeToUnitMap 属性编码到单位的映射
     */
    private void appendUnitToRecord(CraneBusinessRecord record, Map<String, String> propCodeToUnitMap) {
        // 力臂
        if (record.getArmForce() != null) {
            String unit = propCodeToUnitMap.get("arm_force");
            if (unit != null) {
                record.setArmForceWithUnit(record.getArmForce().toString() + unit);
            }else {
                record.setArmForceWithUnit(record.getArmForce().toString());
            }
        }

        // 大臂长度
        if (record.getBigArmLen() != null) {
            String unit = propCodeToUnitMap.get("big_arm_len");
            if (unit != null) {
                record.setBigArmLenWithUnit(record.getBigArmLen().toString() + unit);
            }else {
                record.setBigArmLenWithUnit(record.getBigArmLen().toString());
            }
        }

        // 水平度X
        if (record.getLevelX() != null) {
            String unit = propCodeToUnitMap.get("level_x");
            if (unit != null) {
                record.setLevelXWithUnit(record.getLevelX().toString() + unit);
            }else {
                record.setLevelXWithUnit(record.getLevelX().toString());
            }
        }

        // 水平度Y
        if (record.getLevelY() != null) {
            String unit = propCodeToUnitMap.get("level_y");
            if (unit != null) {
                record.setLevelYWithUnit(record.getLevelY().toString() + unit);
            }else {
                record.setLevelYWithUnit(record.getLevelY().toString());
            }
        }

        // 风速
        if (record.getWindSpeed() != null) {
            String unit = propCodeToUnitMap.get("wind_speed");
            if (unit != null) {
                record.setWindSpeedWithUnit(record.getWindSpeed().toString() + unit);
            }else {
                record.setWindSpeedWithUnit(record.getWindSpeed().toString());
            }
        }

        // 回转角度
        if (record.getRotation() != null) {
            String unit = propCodeToUnitMap.get("rotation");
            if (unit != null) {
                record.setRotationWithUnit(record.getRotation().toString() + unit);
            }else {
                record.setRotationWithUnit(record.getRotation().toString());
            }
        }

        // 俯仰角
        if (record.getPitch() != null) {
            String unit = propCodeToUnitMap.get("pitch");
            if (unit != null) {
                record.setPitchWithUnit(record.getPitch().toString() + unit);
            }else {
                record.setPitchWithUnit(record.getPitch().toString());
            }
        }

        // 主钩力矩
        if (record.getMoment() != null) {
            String unit = propCodeToUnitMap.get("moment");
            if (unit != null) {
                record.setMomentWithUnit(record.getMoment().toString() + unit);
            }else {
                record.setMomentWithUnit(record.getMoment().toString());
            }
        }

        // 主钩吊重
        if (record.getWeight() != null) {
            String unit = propCodeToUnitMap.get("weight");
            if (unit != null) {
                record.setWeightWithUnit(record.getWeight().toString() + unit);
            }else {
                record.setWeightWithUnit(record.getWeight().toString());
            }
        }

        // 倾斜度
        if (record.getInclination() != null) {
            String unit = propCodeToUnitMap.get("inclination");
            if (unit != null) {
                record.setInclinationWithUnit(record.getInclination().toString() + unit);
            }else {
                record.setInclinationWithUnit(record.getInclination().toString());
            }
        }

        // 风级
        if (record.getWindLevel() != null) {
            String unit = propCodeToUnitMap.get("wind_level");
            if (unit != null) {
                record.setWindLevelWithUnit(record.getWindLevel().toString() + unit);
            }else {
                record.setWindLevelWithUnit(record.getWindLevel().toString());
            }
        }

        // 臂尖高度
        if (record.getArmHeight() != null) {
            String unit = propCodeToUnitMap.get("arm_height");
            if (unit != null) {
                record.setArmHeightWithUnit(record.getArmHeight().toString() + unit);
            }else {
                record.setArmHeightWithUnit(record.getArmHeight().toString());
            }
        }

        // 作业时长
        if (record.getWorkHour() != null) {
            String unit = propCodeToUnitMap.get("work_hour");
            if (unit != null) {
                record.setWorkHourWithUnit(record.getWorkHour().toString() + unit);
            }else {
                record.setWorkHourWithUnit(record.getWorkHour().toString());
            }
        }

        // 怠速时长
        if (record.getIdlingHour() != null) {
            String unit = propCodeToUnitMap.get("idling_hour");
            if (unit != null) {
                record.setIdlingHourWithUnit(record.getIdlingHour().toString() + unit);
            }else {
                record.setIdlingHourWithUnit(record.getIdlingHour().toString());
            }
        }

        // 总工作时长
        if (record.getWorkTotalHour() != null) {
            String unit = propCodeToUnitMap.get("work_total_hour");
            if (unit != null) {
                record.setWorkTotalHourWithUnit(record.getWorkTotalHour().toString() + unit);
            }else {
                record.setWorkTotalHourWithUnit(record.getWorkTotalHour().toString());
            }
        }
    }

    @Override
    public CraneBusinessRecord queryById(Integer id) {
        CraneBusinessRecord craneBusinessRecord = baseMapper.selectById(id);
        if (craneBusinessRecord != null) {
            Double sumWeight = baseMapper.sumWeightByDay(craneBusinessRecord.getTenantId(), craneBusinessRecord.getMechanicalId(),  new Date());
            if (sumWeight == null) {
                sumWeight = 0.0;
            }
            craneBusinessRecord.setTotalWeight(sumWeight);
        }
        return craneBusinessRecord;
    }

    @Override
    public List<CraneBusinessDayStatsics> countByDay(CraneBusinessDayStatsicsReq statisticsVO) {
        // 计算两个时间之间所有的天
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        List<Date> timeList = null;
        try {
            timeList = DateUtil.findDates(statisticsVO.getStartTime(), statisticsVO.getEndTime());
            if (CollectionUtil.isEmpty(timeList)) {
                return null;
            }
        } catch (ParseException e) {
            log.error("countByDay 时间转换异常");
            throw new RuntimeException("countByDay 时间转换异常" + e.getMessage());
        }
        String mechanicalId = statisticsVO.getMechanicalId();
        List<CraneBusinessDayStatsics> craneBusinessDayStatsicsList = new ArrayList<>();
        for (Date date : timeList) {
            CraneBusinessDayStatsics craneBusinessDayStatsics = new CraneBusinessDayStatsics();
            craneBusinessDayStatsics.setDay(cn.hutool.core.date.DateUtil.format(date, "yyyy-MM-dd"));
            Double sumWeight = baseMapper.sumWeightByDay(tenantId, mechanicalId, date);
            if (sumWeight == null) {
                sumWeight = 0.0;
            }
            craneBusinessDayStatsics.setTotalWeight(sumWeight);
            Date yesterday = cn.hutool.core.date.DateUtil.offsetDay(date, -1);
            Long hoistingTimes = baseMapper.countMaxHoistingTimesByDay(tenantId, mechanicalId, date);
            if (hoistingTimes == null) {
                hoistingTimes = 0L;
            }
            Long yesterdayHoistingTimes = baseMapper.countMaxHoistingTimesByDay(tenantId, mechanicalId, yesterday);
            if (yesterdayHoistingTimes == null) {
                yesterdayHoistingTimes = 0L;
            }
            Long totalHoistingTimes = hoistingTimes - yesterdayHoistingTimes;
            craneBusinessDayStatsics.setTotalHoistingTimes(totalHoistingTimes>0?totalHoistingTimes:0L);
            craneBusinessDayStatsicsList.add(craneBusinessDayStatsics);
        }
        return craneBusinessDayStatsicsList;
    }


}